package ms.authority.service;

import ms.authority.bean.UserParamBean;
import ms.authority.bean.UserQueryParamBean;
import ms.authority.config.ResponseCode;
import ms.authority.dao.UserDao;
import ms.authority.entity.Permission;
import ms.authority.entity.User;
import ms.common.exception.BizException;
import page.Page;
import ms.common.util.bean.BeanUtil;
import ms.common.util.string.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Project Name: itye
 * File Name: UserService
 * Package Name: ms.authority.service
 * Date: 2018/5/3  14:28
 * Copyright (c) 2018, tianyul All Rights Reserved.
 * 用户业务层
 */
@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    /**
     * 分页查询
     * @param userQueryParamBean
     * @param key
     * @return
     */
    // 因为配置文件继承了CachingConfigurerSupport，所以没有指定key的话就是用默认KEY生成策略生成,我们这里指定了KEY
    // value属性指定Cache名称
    // 使用key属性自定义key
    // condition属性指定发生的条件(如上示例表示只有当user的id为偶数时才会进行缓存, condition = "#id%2==0")
    @Cacheable(value = "queryUserPage", key = "'queryUserPage' + #userQueryParamBean.pageNo", condition="#key==''" )
    public Page<User> queryPage(UserQueryParamBean userQueryParamBean, String key) {
        //构造请求参数
        User user = new User();
        user.setRealName(userQueryParamBean.getRealName());
        user.setStatus(userQueryParamBean.getStatus());

        return userDao.getPage(userQueryParamBean.getPageNo(), userQueryParamBean.getPageSize(),User.class, user);
    }

    /**
     * 新增
     * @param userParamBean
     * @return
     */
    @CacheEvict(value= {"queryUserPage"},allEntries=true)// 清空 user_detail queryPage 缓存
    public void create(UserParamBean userParamBean) {
        //查询用户是否存在
        User userParam = new User();
        userParam.setUserName(userParamBean.getUserName());
        User existUser = userDao.findOneByBean(userParam, User.class);

        if(!StringUtil.isEmpty(existUser)) {
            throw new BizException(ResponseCode.USER_EXIST,"用户账号已经存在");
        }

        User user = BeanUtil.copy(userParamBean, User.class);
        user.setUrls(getUrls(userParamBean.getPermissions()));
        user.setStatus(1);
        user.setCreateTime(System.currentTimeMillis());
        user.setUpdateTime(System.currentTimeMillis());
        userDao.insert(user);
    }

    /**
     * 修改
     * @param userParamBean
     */
    @Caching(put = @CachePut(value = "user_detail", key = "'user_detail' + #userParamBean.id"), evict = { @CacheEvict(value = "queryUserPage", allEntries = true)})
    public void update(UserParamBean userParamBean) {
        //查询用户是否存在
        User existUser = userDao.findOneById(userParamBean.getId(), User.class);

        if(StringUtil.isEmpty(existUser)) {
            throw new BizException(ResponseCode.USER_UN_EXIST,"用户信息不存在");
        }

        User user = BeanUtil.copy(userParamBean, User.class);
        user.setUrls(getUrls(userParamBean.getPermissions()));
        user.setUpdateTime(System.currentTimeMillis());
        userDao.update(user, User.class);
    }

    /**
     * 启用
     * @param id
     */
    @Caching(put = @CachePut(value = "user_detail", key = "'user_detail' + #id"), evict = { @CacheEvict(value = "queryUserPage", allEntries = true)})
    public void use(String id) {
        //查询用户是否存在
        User existUser = userDao.findOneById(id, User.class);

        if(StringUtil.isEmpty(existUser)) {
            throw new BizException(ResponseCode.USER_UN_EXIST,"用户信息不存在");
        }
        if(1 == existUser.getStatus()) {
            throw new BizException(ResponseCode.USER_STATUS_ERROR,"用户状态错误");
        }

        User user = new User();
        user.setId(id);
        user.setStatus(1);
        userDao.update(user, User.class);
    }

    /**
     * 停用
     * @param id
     */
    /**
     * @Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。
     * 其拥有三个属性：cacheable、put和evict，分别用于指定@Cacheable、@CachePut和@CacheEvict。
     */
    @Caching(put = @CachePut(value = "user_detail", key = "'user_detail' + #id"), evict = {@CacheEvict(value = "queryUserPage", allEntries = true)})
    public void cancel(String id) {
        //查询用户是否存在
        User existUser = userDao.findOneById(id, User.class);

        if(StringUtil.isEmpty(existUser)) {
            throw new BizException(ResponseCode.USER_UN_EXIST,"用户信息不存在");
        }
        if(2 == existUser.getStatus()) {
            throw new BizException(ResponseCode.USER_STATUS_ERROR,"用户状态错误");
        }

        User user = new User();
        user.setId(id);
        user.setStatus(2);
        userDao.update(user, User.class);
    }

    /**
     * 详情
     * @param id
     */
    @Cacheable(value = "user_detail", key = "'user_detail' + #id")
    public User detail(String id) {
        //查询用户是否存在
        User existUser = userDao.findOneById(id, User.class);

        if(StringUtil.isEmpty(existUser)) {
            throw new BizException(ResponseCode.USER_UN_EXIST,"用户信息不存在");
        }
        return existUser;
    }

    private List<String> getUrls(List<Permission> permissions) {
        List<String> urls = new ArrayList<>();
        if(StringUtil.isEmpty(permissions)) {
            return urls;
        }
        permissions.forEach(permission -> {
            urls.add(permission.getUrl());
            if(null != permission.getChildren()) {
                urls.addAll(getUrls(permission.getChildren()));
            }
        });
        return urls;
    }
}
